package cn.com.zetatech.maple.parser.processor.impl;

import cn.com.zetatech.maple.entity.Field;
import cn.com.zetatech.maple.entity.Rule;
import cn.com.zetatech.maple.parser.processor.LineProcessor;
import cn.com.zetatech.maple.parser.utils.ScriptEnginePool;
import org.apache.commons.lang3.StringUtils;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 设备日志处理器
 *
 * @author cheng.cao@zetatech.com.cn
 */
public class DeviceLogLineProcessor implements LineProcessor<Map<String, String>> {

    /**
     * 这种解析方式并不好，时间复杂度不好计算，至少为O(n*m)
     * 如果有时间的话，可模拟”中缀表达式”算法提速,提速后时间复杂度为O(n)，空间复杂度O(m)
     */
    @Override
    public Map<String, String> processLine(File file, String line, Rule fields) throws IOException {
        Map<String, String> result = new TreeMap<>();
        for (Field field : fields.getFields()) {
            boolean ignore = field.isIgnore();
            if (ignore) {
                continue;
            }
            String value = field.getValue();
            String prefix = field.getPrefix();
            String property = field.getProperty();
            String column = field.getColumn();
            String script = field.getScript();
            if (value != null) {
                if (value.contains("${file_name}")) {
                    value = value.replace("${file_name}#", "");
                    Pattern pattern = Pattern.compile(value);
                    Matcher m = pattern.matcher(file.getAbsolutePath());
                    if (m.find()) {
                        result.put(column, m.group());
                    }
                } else {
                    // 认为是固定值
                    result.put(column, value);
                }
                continue;
            }

            if (prefix == null) {
                int propertyIndex = line.indexOf(property);
                if (propertyIndex > -1) {
                    setValue(line, result, property, column, propertyIndex);
                }
            } else {
                int prefixIndex = line.indexOf(prefix);
                if (prefixIndex > -1) {
                    String prefixSubString = line.substring(prefixIndex + prefix.length());
                    int propertyIndex = prefixSubString.indexOf(property);
                    setValue(prefixSubString, result, property, column, propertyIndex);
                }
            }
            // 调用脚本处理后续逻辑
            if (result.get(column) != null && StringUtils.isNotBlank(script)) {
                String engineName = field.getScriptEngine();
                // 默认脚本引擎:groovy
                if (engineName == null || "".equalsIgnoreCase(engineName.trim())) {
                    engineName = "groovy";
                }
                ScriptEngine engine = ScriptEnginePool.getEngine(engineName.toLowerCase());
                Bindings bindings = engine.createBindings();
                bindings.put("fieldVal", result.get(column));
                bindings.put("line", line);
                bindings.put("file", file.getAbsolutePath());
                try {
                    String processResult = (String) engine.eval(script, bindings);
                    result.put(column, processResult);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        return result;
    }

    private void setValue(String line, Map<String, String> data, String property, String column, int propertyIndex) {
        String propertySubString = line.substring(propertyIndex + property.length());
        String[] subItems = propertySubString.split(" ");
        String value = subItems[0];
        if (value != null && value.startsWith(":")) {
            value = value.substring(1);
        }
        data.put(column, value);
    }

}
